﻿using CPPEI.WebApi;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Xml;

namespace CPPEI.WebApi2
{
    public static class ActionFactory
    {
        public static bool HasInitiated { get; private set; }

        private static List<CPPEI.WebApi.Runtime.ModuleRegInfo> s_moduleRegInfos = new List<CPPEI.WebApi.Runtime.ModuleRegInfo>();
        private static List<BaseModule> s_moduleList = new List<BaseModule>();

        public static void Init()
        {
            foreach (Config.Module module in Config.Current.Modules)
            {
                Assembly moduleAssembly = null;
                try
                {
                    moduleAssembly = Assembly.Load(module.Assembly);
                }
                catch (Exception ex)
                {

                }

                CPPEI.WebApi.Runtime.ModuleRegInfo moduleRegInfo = null;
                if (moduleAssembly != null)
                {
                    moduleRegInfo = new CPPEI.WebApi.Runtime.ModuleRegInfo();
                    moduleRegInfo.Name = module.Name;
                    moduleRegInfo.Assembly = moduleAssembly;
                    s_moduleRegInfos.Add(moduleRegInfo);

                    BaseModule moduleInst = moduleAssembly.CreateInstance(module.Type) as BaseModule;
                    if(moduleInst!=null)
                    {
                        moduleInst.Name = module.Name;
                        s_moduleList.Add(moduleInst);
                    }
                }

                Type[] types = moduleAssembly.GetTypes();
                foreach (Type actionType in types)
                {
                    ActionAttribute actionAttr = actionType.GetCustomAttribute<ActionAttribute>();
                    if(actionAttr!=null)
                    {
                        CPPEI.WebApi.Runtime.ScenarioRegInfo scenario = moduleRegInfo.AddOrGet(actionAttr.Scenario);

                        scenario.Add(new CPPEI.WebApi.Runtime.ActionRegInfo(actionAttr.Name, actionType, actionAttr.HttpMethod, actionAttr.IsAnonymous));
                    }
                }
            }
        }

        public static IAction GetAction(SysParams sysParams)
        {
            CPPEI.WebApi.Runtime.ModuleRegInfo module = GetModule(sysParams.Module);
            if (module == null)
            {
                return null;
            }

            CPPEI.WebApi.Runtime.ActionRegInfo actionRegInfo = module.GetAction(sysParams.Scenario, sysParams.Action);
            if (actionRegInfo == null)
            {
                return null;
            }

            BaseModule moduleInst = null;
            for (int index = 0; index < s_moduleList.Count; index++)
            {
                if (string.Equals(s_moduleList[index].Name, sysParams.Module, StringComparison.CurrentCultureIgnoreCase))
                {
                    moduleInst = s_moduleList[index];
                    break;
                }
            }

            if (moduleInst == null)
            {
                return null;
            }

            if(moduleInst.HasInitiated == false)
            {
                lock(moduleInst)
                {
                    if(moduleInst.HasInitiated == false)
                    {
                        moduleInst.Initiate();
                    }
                }
            }

            BaseAction action = (BaseAction)Activator.CreateInstance(actionRegInfo.Type);
            action.HttpMethod = actionRegInfo.HttpMethod;
            action.IsAnonymous = actionRegInfo.IsAnonymous;

            return action;
        }
        private static CPPEI.WebApi.Runtime.ModuleRegInfo GetModule(string name)
        {
            for (int index = 0; index < s_moduleRegInfos.Count; index++)
            {
                if(string.Equals(s_moduleRegInfos[index].Name, name, StringComparison.CurrentCultureIgnoreCase))
                {
                    return s_moduleRegInfos[index];
                }
            }
            return null;
        }

        public static T GetCustomAttribute<T>(this Type type)
        {
            object[] attrArr = type.GetCustomAttributes(typeof(T), true);

            if(attrArr!=null && attrArr.Length > 0)
            {
                return (T)attrArr[0];
            }
            return default(T);
        }
        public static T GetCustomAttribute<T>(this PropertyInfo property)
        {
            object[] attrArr = property.GetCustomAttributes(typeof(T), true);

            if (attrArr != null && attrArr.Length > 0)
            {
                return (T)attrArr[0];
            }
            return default(T);
        }
        public static T GetCustomAttribute<T>(this FieldInfo field)
        {
            object[] attrArr = field.GetCustomAttributes(typeof(T), true);

            if (attrArr != null && attrArr.Length > 0)
            {
                return (T)attrArr[0];
            }
            return default(T);
        }
    }

    //public class WebApiAssembly
    //{
    //    public string Assembly { get; set; }

    //    public List<ActionEntry> Actions = new List<ActionEntry>();

    //    public WebApiAssembly(string assembly)
    //    {
    //        Assembly = assembly;
    //    }

    //    public class ActionEntry
    //    {
    //        public string Type { get; set; }

    //        public ActionEntry(string type)
    //        {
    //            Type = type;
    //        }
    //    }
    //}
}
